<?php
declare(strict_types=1);

namespace app\traits;

use app\model\AdminConfig;
use app\model\AdminPermission;
use Symfony\Polyfill\Uuid\Uuid;
use think\facade\Session;
use app\model\AdminUserToken;
use app\model\AdminRolePermission;
use app\model\MyRedis;
use app\model\AdminUser;

/**
 * model 公共方法
 *
 * Class MyModelTrait
 * @package app\traits
 */
trait MyModelTrait
{
    /**
     * 生成密码
     *
     * @param string $password
     * @param string $salt
     * @return string
     */
    public static function generatePassword(string $password, string $salt): string
    {
        return hash('sha256', $password.$salt);
    }// generatePassword() end

    /**
     * 生成 token
     *
     * @return string
     */
    public static function generateToken(): string
    {
        // 7af359ec-3922-40fc-be19-4f4455ac2905, 长度 36
        return Uuid::uuid_create();
    }// generateLog() end

    /**
     * 生成 token key
     *
     * @param string $token
     * @return string
     */
    public static function generateTokenKey(string $token): string
    {
        return substr($token, 0, 8).substr($token, -8, 8);
    }// generateTokenKey() end

    /**
     * 生成登录会话
     *
     * @param array $admin_user
     */
    public static function generateLoginSession(array $admin_user): void
    {
        $token         = self::generateToken();
        $token_key     = AdminUser::getTokenKey((int)$admin_user['id']);
        $admin_role_id = (int)$admin_user['admin_role_id'];

        // header 传 token 的形式
        //$token_key = "admin_user.".self::generateTokenKey($token);

        Session::set('admin_user.id', $admin_user['id']);
        Session::set('admin_user.account', $admin_user['account']);
        Session::set('admin_user.nickname', $admin_user['nickname']);
        Session::set('admin_user.admin_role_id', $admin_role_id);
        Session::set($token_key, $token);
        AdminRolePermission::setPermissionIdsForSession($admin_user['admin_role_id']);// 设置角色权限 ID
        // 设置角色权限缓存数据
        AdminRolePermission::setRolePermissionToCache(AdminPermission::getPermission());

        // admin_config 设置
        $watermark_switch = AdminConfig::getContent('watermark_switch');
        $copyright        = AdminConfig::getContent('copyright');
        Session::set('config.watermark_switch', $watermark_switch);
        Session::set('config.copyright', $copyright);

        $redis = MyRedis::generateRedisInstance();
        $redis->setex($token_key, MyRedis::EXPIRE_TIME, $token);
        // 表是保留功能
        // AdminUserToken::setToken($admin_user['id'], $token);
    }// generateLoginSession() end

    /**
     * 生成密码盐
     *
     * @param int $length 长度
     * @return string
     */
    public static function generateSalt(int $length = 8): string
    {
        $str      = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        $len      = strlen($str) - 1;
        $rand_str = '';

        for($i = 0; $i < $length; $i++){
            $num       = mt_rand(0, $len);
            $rand_str .= $str[$num];
        }
        return $rand_str;
    }// generateSalt() end

    /**
     * 获取搜索数据
     *
     * @param string $namespace  \app\model\ModelName::class
     * @param string $where       $where .= " AND field = :field";
     * @param array  $raw         $raw['field'] = "xxx";
     * @param int    $page
     * @param int    $limit
     * @param array  $order
     * @return array
     */
    public static function searchForShow(
        string $namespace,
        string $where = "",
        array  $raw = [],
        int    $page = 1,
        int    $limit = 10,
        array  $order = ['id', 'desc']
    ): array {
        // 示例：
        // $where .= " AND field = :field";
        // $raw['field'] = "xxx";
        // $where = trim($where, " AND");
        if (1 > $page) $page = 1;
        if (1 > $limit) $limit = 10;

        $total  = 0;
        $data   = [];
        $offset = $page * $limit - $limit;
        if (class_exists($namespace) === false) return [$total, $data];

        $model = new $namespace();
        $where = trim($where, " AND");
        $where = trim($where, " OR");

        if (strlen($where) < 5 || empty($raw))
        {
            $total = $model->field('id')->count();
            $data  = $model->limit($offset, $limit)->order($order[0], $order[1])->select()->toArray();
        } else {
            $total = $model->whereRaw($where, $raw)->count();
            $data  = $model->whereRaw($where, $raw)->limit($offset, $limit)->order($order[0], $order[1])->select()->toArray();
        }
        return [$total, $data];
    }// searchForShow() end
}